#include "ccp903_sm2.h"
//#define Debug
//#define NO_SPEED_TEST
unsigned char sm2_para[32 * 6] =
{
    0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
    0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC,
    0x28, 0xE9, 0xFA, 0x9E, 0x9D, 0x9F, 0x5E, 0x34, 0x4D, 0x5A, 0x9E, 0x4B, 0xCF, 0x65, 0x09, 0xA7, 0xF3, 0x97, 0x89, 0xF5, 0x15, 0xAB, 0x8F, 0x92, 0xDD, 0xBC, 0xBD, 0x41, 0x4D, 0x94, 0x0E, 0x93,
    0x32, 0xC4, 0xAE, 0x2C, 0x1F, 0x19, 0x81, 0x19, 0x5F, 0x99, 0x04, 0x46, 0x6A, 0x39, 0xC9, 0x94, 0x8F, 0xE3, 0x0B, 0xBF, 0xF2, 0x66, 0x0B, 0xE1, 0x71, 0x5A, 0x45, 0x89, 0x33, 0x4C, 0x74, 0xC7,
    0xBC, 0x37, 0x36, 0xA2, 0xF4, 0xF6, 0x77, 0x9C, 0x59, 0xBD, 0xCE, 0xE3, 0x6B, 0x69, 0x21, 0x53, 0xD0, 0xA9, 0x87, 0x7C, 0xC6, 0x2A, 0x47, 0x40, 0x02, 0xDF, 0x32, 0xE5, 0x21, 0x39, 0xF0, 0xA0,
    0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x72, 0x03, 0xDF, 0x6B, 0x21, 0xC6, 0x05, 0x2B, 0x53, 0xBB, 0xF4, 0x09, 0x39, 0xD5, 0x41, 0x23
};
int ccp903_sm2_keygen(int ccp903_fd, unsigned char *wx, int *wxlen, unsigned char *wy, int *wylen, unsigned char *privkey, int *privkeylen)
{
    struct sm2_keygen_api capi =
    {
        .field = FP,
        .plen  = 32,
        .nlen = 32,
        .klen = 32
    };

    memcpy(capi.p, sm2_para, sizeof(sm2_para));

    ioctl(ccp903_fd, _IOC(0x00, CCP903T_PCIE_MAGIC, ACLASS_SM2_GENKEY, sizeof(capi)), &capi);
    if(capi.field != 0)
        return 0;
    memcpy(privkey, capi.pri_key, 32);
    memcpy(wx, capi.pub_x, 32);
    memcpy(wy, capi.pub_y, 32);
    *wxlen = 32;
    *wylen = 32;
    *privkeylen = 32;
    return 1;

}



int  ccp903_sm2_encrpy(int ccp903_fd, unsigned char *mesg, int mesg_len, unsigned char *pub_x, int xlen, unsigned char *pub_y, int ylen, unsigned char *c1,int *c1_len, unsigned char *c2, int *c2_len, unsigned char *c3, int *c3_len)
{
    struct sm2_enc_api capi =
    {
        .field = FP,
        .plen  = 32,
        .nlen = 32,
        .klen = 32
    };

    memcpy(capi.p, sm2_para, sizeof(sm2_para));
    memset(capi.pub_x, 0, 3 * SM2_SIZE);
    memcpy(capi.pub_x + 32 - xlen, pub_x, xlen);
    memcpy(capi.pub_y + 32 - ylen, pub_y, ylen);
    memcpy(capi.mes + 32 - mesg_len, mesg, mesg_len);

    ioctl(ccp903_fd, _IOC(0x00, CCP903T_PCIE_MAGIC, ACLASS_SM2_ENCRYPT, sizeof(capi)), &capi);
    if(capi.field != 0)
    {
        return 0;
    }

    memcpy(c1, capi.c1, 32*2+1);
    memcpy(c2, capi.c2, 32);
    memcpy(c3, capi.c3, 32);
    *c1_len = 32*2+1;//64
    *c2_len = 32;//data len
    *c3_len = 32;//32

    return 1;
}

int  ccp903_sm2_decrypt(int ccp903_fd, unsigned char *pri_key, int pri_key_len, unsigned char *c1,int c1_len, unsigned char *c2, int c2_len, unsigned char *c3, int c3_len, unsigned char *mesg, int *mesg_len)
{
    struct sm2_dec_api capi =
    {
        .field = FP,
        .plen  = 32,
        .nlen = 32,
        .klen = 32
    };
    int i;
    memcpy(capi.p, sm2_para, sizeof(sm2_para));
    memset(capi.pri_key, 0, SM2_SIZE*6);
    memcpy(capi.pri_key + 32 - pri_key_len, pri_key, pri_key_len);
    memcpy(capi.c1 + 32*2+1 - c1_len, c1, c1_len);
    memcpy(capi.c2 + 32 - c2_len, c2, c2_len);
    memcpy(capi.c3 + 32 - c3_len, c3, c3_len);

   //printf("capi struct:\n");

    ioctl(ccp903_fd, _IOC(0x00, CCP903T_PCIE_MAGIC, ACLASS_SM2_DECRYPT, sizeof(capi)), &capi);
    //printf("decrypt worked\n");
    if(capi.field != 0)
    {
#ifdef Debug
    printf("*****error dec*********\n");
    printf("privkey: ");
    for(i = 0; i < pri_key_len; i++)
    {
	printf("%x ",capi.pri_key[i]);
    }
    printf("\n");
    printf("c1: ");
    for(i = 0; i < c1_len; i++)
    {
	printf("%x ",capi.c1[i]);
    }
    printf("\n");
    printf("c2: ");
    for(i = 0; i < c2_len; i++)
    {
	printf("%x ",capi.c2[i]);
    }
    printf("\n");
    printf("c3: ");
    for(i = 0; i < c3_len; i++)
    {
	printf("%x ",capi.c3[i]);
    }
    printf("\n");
#endif
        return 0;
    }
   // printf("decrypt passed\n");
    memcpy(mesg, capi.mes, 32);
    *mesg_len = 32;

    return 1;
}

int ccp903_sm2_sign(int ccp903_fd, unsigned char *hash, int hashlen, unsigned char *privkey, int privkeylen, unsigned char *r, int *rlen, unsigned char *s, int *slen)
{
    struct sm2_sign_api capi =
    {
        .field = FP,
        .plen  = 32,
        .nlen = 32,
        .klen = 32
    };
    int i;
    memcpy(capi.p, sm2_para, sizeof(sm2_para));
    memset(capi.pri_key, 0, 2 * SM2_SIZE);
    memcpy(capi.pri_key + 32 - privkeylen, privkey, privkeylen);
    memcpy(capi.e + 32 - hashlen, hash, hashlen);


    ioctl(ccp903_fd, _IOC(0x00, CCP903T_PCIE_MAGIC, ACLASS_SM2_SIGNATURE_NOID, sizeof(capi)), &capi);
    if(capi.field != 0)
    {
        return 0;
    }

    memcpy(r, capi.r, 32);
    memcpy(s, capi.s, 32);
    *rlen = 32;
    *slen = 32;
#ifdef Debug
    printf("sm2 sign r:");
    for(i = 0; i < 32; i++)
    {
	printf("%x ",r[i]);
    }
    printf("\n");
    printf("sm2 sign s:");
    for(i = 0; i < 32; i++)
    {
	printf("%x ",s[i]);
    }
    printf("\n");
#endif
    return 1;

}


int  ccp903_sm2_verify(int ccp903_fd, unsigned char *hash, int hashlen, unsigned char  *r, int rlen, unsigned char *s, int slen, unsigned char *pub_x, int xlen, unsigned char *pub_y, int ylen)
{
    struct sm2_verify_api capi =
    {
        .field = FP,
        .plen  = 32,
        .nlen = 32,
        .klen = 32
    };

    memcpy(capi.p, sm2_para, sizeof(sm2_para));
    memset(capi.pub_x, 0, 3 * SM2_SIZE);
    memcpy(capi.pub_x + 32 - xlen, pub_x, xlen);
    memcpy(capi.pub_y + 32 - ylen, pub_y, ylen);
    memcpy(capi.e + 32 - hashlen, hash, hashlen);
    memcpy(capi.r + 32 - rlen, r, rlen);
    memcpy(capi.s + 32 - slen, s, slen);

    ioctl(ccp903_fd, _IOC(0x00, CCP903T_PCIE_MAGIC, ACLASS_SM2_VERIFY_NOID, sizeof(capi)), &capi);
    if(capi.field != 0)
        return 0;
    else
        return 1;

}
























